<template>
    <!-- 搜索后左右50%分栏 -->
    <div class="ai-chat-container" >
      <!-- 左50% 聊天区 -->
      <div class="chat-left">
        <div class="chat-history" ref="chatHistory">
          <div
            v-for="(msg, idx) in chatMessages"
            :key="idx"
            :class="['chat-msg', msg.role === 'user' ? 'user' : 'ai']"
          >
            <!-- <div class="msg-content" v-html="msg.content"></div> -->
            <!-- AI 消息：左侧头像 + 气泡 -->
          <template v-if="msg.role === 'ai'">
            <el-avatar
              class="msg-avatar"
              :src="require('@/assets/ai.png')"
              size="medium"
            />
            <div class="msg-content"  v-html="renderMsg(msg.content)"></div>
          </template>

          <!-- 用户消息：只显示气泡，右侧对齐 -->
          <template v-else>
            <div class="msg-content" v-html="renderMsg(msg.content)"></div>
          </template>
          </div>
        </div>
        <div class="chat-input-area">
          <el-input
            v-model="searchText"
            placeholder="请输入你的问题…"
            @keyup.enter.native="onSearch"
            :disabled="loading"
            class="chat-input"
          >
            <el-button
              slot="append"
              type="primary"
              @click="onSearch"
              :loading="loading"
            >
              发送
            </el-button>
          </el-input>
        </div>
      </div>

      <!-- 右50% 预览区 -->
      <div class="chat-right">
        <div class="preview-header">

        <el-button size="mini" round icon="el-icon-star-on" @click="updateShow"
           :disabled="!previewUrl"
          >展示案例
              </el-button>

          <el-button size="mini" round icon="el-icon-download" @click="downloadZip"
           :disabled="!previewUrl"
          >下载
              </el-button>
  
        <el-button size="mini" round icon="el-icon-link" 
              @click="openPreviewWindow()"
          :disabled="!previewUrl"
          >新窗口预览
              </el-button>

           <!-- <el-button size="mini" round icon="el-icon-s-platform" 
              @click="toggleEdit"
          :disabled="!previewUrl && !previewHtml"
          >
           {{ isEditingCode ? '预览效果' : '编辑代码' }}
              </el-button> -->



          <el-button size="mini" type="danger" round icon="el-icon-close" @click="closeChat"
          :disabled="loading"
          >关闭对话
              </el-button>



        </div>
        <div class="preview-body">
          <!-- Loading 状态 -->
          <div v-if="loading && !previewUrl" class="preview-loading">
            <img src="@/assets/jj.png" alt="加载中" class="loading-spinner" />
            <p>正在生成网站，请稍候...</p>
          </div>

        <!-- 编辑模式：代码编辑框 -->
          <el-input
            v-if="isEditingCode"
            type="textarea"
            :rows="20" autosize="true"
            v-model="previewHtml"
            class="code-editor"
          />

          <!-- 预览模式：iframe 渲染          :srcdoc="previewHtml"  :src="previewUrl"  -->
          <iframe
            v-else-if="previewUrl"
            :key="previewKey"
            :src="previewUrl"
            frameborder="0"
            class="preview-iframe"
          ></iframe>
        </div>
      </div>
    </div>
</template>

<script>
import {  saveApp,updateShow,getAppInfo } from '@/api/common'
import { download } from '@/utils/request'
import MarkdownIt from 'markdown-it'
// 按需载入 highlight.js 核心与 html 语法高亮
import hljs from 'highlight.js/lib/core'
import xml from 'highlight.js/lib/languages/xml'
// 注册 HTML 语言（highlight.js 用 xml 实现 html 高亮）
hljs.registerLanguage('html', xml)

const md = new MarkdownIt({
  html: true,
  linkify: true,
  typographer: true,
  highlight: (str, lang) => {
    // lang 是 ``` 后面跟的语言名，比如 html
    if (lang && hljs.getLanguage(lang)) {
      try {
        return `<pre class="hljs"><code>` +
               hljs.highlight(lang, str, true).value +
               `</code></pre>`
      } catch (__) {}
    }
    // 失败回退：不高亮，但转义 html
    return `<pre class="hljs"><code>` +
           md.utils.escapeHtml(str) +
           `</code></pre>`
  }
})


export default {
  name: "chat",
  data() {
    return {
      searchText: this.$route.query.newVal,
      loading: false,
      chatMessages: [],
      previewKey:0,
      isEditingCode: false,//预览-编辑代码
      previewHtml: "",//编辑html
      previewUrl:"",//预览url
       // 新增字段
      appId: '',//应用id
      evtSource: null
    };
  },
  created() {
    //创建应用
    saveApp(this.searchText.trim()).then(res => {
        this.appId = res.data;
        // 页面加载完毕，先调用一次
        this.onSearch();
    }).catch(() => {     
        this.$message.error("创建应用失败")
    });
  },
  methods: {
    //收藏
    updateShow(){
      updateShow(this.appId).then(res => {
          this.$message.success("展示成功");//弹框提示信息
        }).catch(() => {     
          this.$message.error("展示失败")
        });
    },
    renderMsg(text) {
      // 将 Markdown+HTML 混合渲染，代码块会高亮显示
      return md.render(text);
    },
     async onSearch() {
      if (!this.searchText.trim()) return;
      const newsearchText = this.searchText.trim();
      // 1. 确保先创建应用，拿到 appId
      // 重置预览状态
      this.loading = true;
      this.searchText="";;
      this.previewHtml = "";
      this.previewUrl="";
      this.previewKey++;
      this.chatMessages.push({ role: "user", content: newsearchText });
      // 关闭旧的 SSE
      if (this.evtSource) {
        this.evtSource.close();
      }
      const url = process.env.VUE_APP_API_BASE+`app/chat/workflowGenCode?appId=${this.appId}&message=${encodeURIComponent(newsearchText)}`;
      const source = new EventSource(url);

      // 当后端用 default event (message) 发送数据时触发
      source.addEventListener("message", (e) => {
        if (!e.data) return;
        let chunk = "";
        if (e.data.trim().startsWith("{")) {
            try {
              const parsed = JSON.parse(e.data);
              chunk = parsed.d ?? "";
            } catch (err) {
              console.warn("JSON 解析失败，直接作为文本处理：", e.data);
              chunk = e.data;
            }
          } else {
            // 纯文本，直接使用
            chunk = e.data;
          }
        if (chunk) {
          // 推入新的 AI 内容
          //this.chatMessages.push({ role: "ai", content: chunk });
          // 1. 如果最后一条已经是 AI，就追加到它上面
          const last = this.chatMessages[this.chatMessages.length - 1];
          if (last && last.role === "ai") {
            last.content += chunk;
          } else {
            // 2. 否则新建一个 AI 气泡
            this.chatMessages.push({ role: "ai", content: chunk });
          }
          // 滚动到底部
          this.$nextTick(() => {
            const ch = this.$refs.chatHistory;
            ch.scrollTop = ch.scrollHeight;
          });
        }
      });
      // 监听 done 事件关闭流
      source.addEventListener("done", () => {
        this.loading = false;
        source.close();

        // 取最后一条 AI 消息
        // const lastMsg = [...this.chatMessages].reverse().find(m => m.role === "ai");
        // if (lastMsg) {
        //   const text = lastMsg.content;
        //   // 用正则提取从第一个 '<' 到最后一个 '</html>'
        //   const match = text.match(/<!DOCTYPE[\s\S]*?<\/html>/i);
        //   this.previewHtml = match ? match[0] : "";
        // }

         getAppInfo(this.appId).then(res => {
            if('vue'===res.data.codeGenType){
                this.previewUrl=process.env.VUE_APP_WEB_BASE+"vue_"+this.appId+"/dist/index.html";
            }else{
                this.previewUrl=process.env.VUE_APP_WEB_BASE+"html_"+this.appId+"/index.html";
            }
        });

        // 强制刷新 iframe
        this.previewKey++;
      });
    //   source.addEventListener("error", (e) => {
    //     this.$message.error(e.data || "输入不合规，请检查后重试！");
    //     this.loading = false;
    //     source.close();
    // });

      source.onerror = (e) => {
          console.log("接口返回1："+JSON.stringify(e))
        // 这里捕捉到后端 500 或断开等异常
        // 弹出错误提示
        this.loading = false;
        source.close();
      };
      this.evtSource = source;
    },

    // 如果切回预览，强制刷新 iframe
    toggleEdit() {
      this.isEditingCode = !this.isEditingCode;
      if (!this.isEditingCode) {
        this.previewKey++;
      }
    },
    closeChat() {
        this.$confirm('确认要关闭对话?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
            // 关闭 SSE
            if (this.evtSource) {
              this.evtSource.close();
              this.evtSource = null;
            }
            // 恢复初始状态
            this.appId="";
            this.chatMessages = [];
            this.previewHtml = "";
            this.searchText = "";
            this.loading = false;
            // this.$router.push({
            //   name: 'home'
            // })
            // 路由跳转
            this.$router.push('/home').then(() => {
              // 强制刷新当前页面
              this.$router.go(0) // 或者 window.location.reload()
            })
        }).catch(() => {     
        });
      
    },
     /** 新窗口打开预览 */
    openPreviewWindow() {
      const url = this.previewUrl;
      if (url) {
        window.open(url, '_blank');
    }
  },
  // 下载压缩包
    async downloadZip() {
      let appId=this.appId;
      download('static/download', { appId }, appId+'.zip',null );
    },
  },
  beforeDestroy() {
    // 组件卸载前，确保关闭 SSE
    if (this.evtSource) {
      this.evtSource.close();
    }
  },
};
</script>

<style scoped>

/* 搜索后聊天 & 预览区 */
.ai-chat-container {
    height: calc(100vh - 64px);
  flex: 1;
  display: flex;
  background: #f4f6fa;
  overflow: hidden;            /* 禁用外层滚动 */
}

.chat-left {
  flex: 3;
  display: flex;
  flex-direction: column;
  background: #fff;
  border-right: 1px solid #ebeef5;
  overflow: hidden;            /* 禁用此层滚动 */
}

.chat-right {
  flex: 7;
  display: flex;
  flex-direction: column;
  background: #fafdff;
  position: relative;
  overflow: hidden;            /* 禁用此层滚动 */
}

/* 左侧聊天内容区滚动 */
.chat-history {
  flex: 1;
  overflow-y: auto;
  padding: 28px 24px 12px;
}

/* 左侧输入区固定 */
.chat-input-area {
  flex-shrink: 0;
  padding: 14px 20px;
  border-top: 1px solid #f0f0f0;
  background: #fff;
}

/* 气泡样式 */
.chat-msg {
  display: flex;
  width: 100%;
  margin-bottom: 14px;
}
.chat-msg.user {
  justify-content: flex-end;
}
.chat-msg.ai {
  justify-content: flex-start;
}
.msg-content {
  max-width: 74%;
  padding: 10px 18px;
  border-radius: 10px;
  font-size: 15px;
  line-height: 1.7;
  word-break: break-word;
  box-shadow: 0 2px 8px #f1f2f6;
  
}
.chat-msg.user .msg-content {
  background: #e7f2fe;
  color: #1967d2;
}
.chat-msg.ai .msg-content {
  background: #f2f6fc;
  color: #333;
}

/* 预览区右栏滚动 */
/* .preview-header {
  flex-shrink: 0;
  background: #fff;
  border-bottom: 1px solid #ececec;
  text-align: right;
  padding: 12px 18px;
} */
/* 右侧预览头部按钮 */
.preview-header {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  background: #fff;
  border-bottom: 1px solid #ececec;
  padding: 12px 18px;
}
.preview-header .el-button {
  margin-left: 8px;
}
.preview-body {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
}
/* Loading 容器：水平垂直居中 */
.preview-loading {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
/* 旋转动画 */
.loading-spinner {
  width: 64px;
  height: 64px;
  animation: spin 3s linear infinite;
  margin-bottom: 12px;
}

/* 文字提示 */
.preview-loading p {
  margin: 0;
  font-size: 14px;
  color: #666;
}

/* 关键帧动画 */
@keyframes spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}
/* 代码编辑框样式 */
.code-editor {
  flex: 1;
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  padding: 16px;
  background: #f5f7fa;
  font-family: "Courier New", monospace;
  font-size: 14px;
  line-height: 1.5;
  overflow: auto;
  flex-direction: column;
}

.preview-iframe {
  width: 100%;
  height: 100%;
  border: none;
  border-radius: 10px;
  box-shadow: 0 2px 8px #f0f1f3;
}
/* AI 头像 */
.msg-avatar {
  margin-right: 8px;
  flex-shrink: 0;
}



/* 调整 chat-msg 布局，让头像和气泡水平排列 */
.chat-msg {
  display: flex;
  width: 100%;
  margin-bottom: 14px;
}
.chat-msg.ai {
  justify-content: flex-start; /* AI 消息左对齐 */
  align-items: flex-start;     /* 头像和气泡顶端对齐 */
}
.chat-msg.user {
  justify-content: flex-end;   /* 用户消息右对齐 */
  align-items: flex-end;       /* 如果你给用户头像也用同样结构，可以用这行 */
}

/* 用深度选择器命中 v-html 插入的 <pre> */
.msg-content >>> pre {
  display: block;
  max-width: 100%;
  padding: 8px;
  margin: 8px 0;
  background: #f5f7fa;
  border-radius: 6px;
  box-sizing: border-box;

  /* 横向滚动，保留原始空格和换行 */
  white-space: pre;
  overflow-x: auto;
}

/* 如果你也要强制让内联 <code> 换行，可以再加： */
.msg-content >>> code {
  white-space: pre-wrap;
  word-break: break-all;
}
</style>



